USEROBJECT MenuClass
Create a drop down menu at your leisure and show it when you're ready. This is a very basic context menu, nothing advanced. Usage local menu = MenuClass:New() menu:AddItem('Do Something', function() SendChatMessage("Hello Bob!", "WHISPER", "Common", "Bob") end) menu:AddItem('Close', function() -- do nothing, just close. end) local f = SomeClickableFrame f:SetScript('OnClick', function(self, button) menu:Show() end) Properties ;.menuItems : Table. Stores the menu items. ;.anchor : String. The anchor. ;.x : The x offset ;.y : The y offset ;.displayMode : The display mode. ;.autoHideDelay : The time it takes for the menu to automatically hide. ;.menuFrame : The menu frame. ;.uniqueID : A self incrementing number used to ensure that the generic menu frame is unique. ;.isTitle : Is this menu item a header? 1 if yes, nil if no. Methods ;:Activate() : Creates the menu frame if it has not already been set with :SetMenuFrame(). ;:AddItem( text, func, isTitle) : Add a menu item with text text that does func. Requires at least 1. ;:GetAttribute( text, attribute) : Gets an attribute for the given menu item. ;:New() : Allocate memory for the new menu and set the defaults. Required. Returns the menu. ;:RemoveItem( text) : Remove the first menu item that matches text ;:SetAnchor( anchor) : Set the anchor. Optional. Default: "cursor" ;:SetAttribute( text, attribute, value) : Sets an attribute for the given menu item. ;:SetDisplayMode( displayMode) : Set the displayMode. Optional. Default: "MENU" ;:SetAutoHideDelay( autoHideDelay) : Set the autoHideDelay. Optional. Default: nil (does not auto close) ;:SetMenuFrame( menuFrame) : Set the menuFrame. Optional. Default: self generating menuFrame. If set, this must be a frame that inherits UIDropDownMenuTemplate. ;:SetX( xsave) : Set the x'' offset. Optional. Default: nil (0 if ''anchor is not "cursor"). If save resolves to true, x'' will be added to rather than replaced. ;:SetY( ysave) : Set the ''y offset. Optional. Default: nil (0 if anchor is not "cursor"). If save resolves to true, y will be added to rather than replaced. ;:Show() : Show the menu. Code -- Set to false to use file-scoped variables or true to use the new addon-scoped variables local useAddonScope = true local addonName, MenuClass if useAddonScope then addonName, MenuClass = ... else addonName, MenuClass = "--your addon's name--", {} end function MenuClass:New() local ret = {} -- set the defaults ret.menuList = {} ret.anchor = 'cursor'; -- default at the cursor ret.x = nil; ret.y = nil; ret.displayMode = 'MENU'; -- default ret.autoHideDelay = nil; ret.menuFrame = nil; -- If not defined, :Show() will create a generic menu frame ret.uniqueID = 1 -- import the functions for k,v in pairs(self) do retk = v end -- return a copy of the class return ret end -- Return the index where "text" lives. ; text : The text to search for. -- function MenuClass:GetItemByText(text) for k,v in pairs(self.menuList) do if v.text text then return k end end end -- Add menu items ; text : The display text. ; func : The function to execute OnClick. ; isTitle : 1 if this is a header (usually the first one) returns the last index of the menu item that was just added. -- function MenuClass:AddItem(text, func, isTitle) local info = {} info"text" = text info"isTitle" = isTitle info"func" = func table.insert(self.menuList, info) return #self.menuList end -- Set an attribute for the menu item. Valid attributes are found in the FrameXML\UIDropDownMenu.lua file with their valid values. Arbitrary non-official attributes are allowed, but are only useful if you plan to access them with :GetAttribute(). ; text : The text of the menu item or index of the menu item. ; attribute : Set this attribute to "value". ; value : The value to set the attribute to. -- function MenuClass:SetAttribute(text, attribute, value) self.menuListor (self.menuList[text and text) or 1]or "uniqueID" = value end -- Get an attribute for the menu item. Valid attributes are found in the FrameXML\UIDropDownMenu.lua file with their valid values or any arbitrary attribute set with :SetAttribute(). ; text : The text of the menu item or index of the menu item. ; attribute : Get this attribute. -- function MenuClass:GetAttribute(text, attribute) return self.menuListor (self.menuList[text and text) or 1]or "uniqueID" end -- Remove the first item matching "text" ; text : The text to search for. -- function MenuClass:RemoveItem(text) table.remove(self.menuList, self:GetItemByText(text)) end -- ; anchor : Set the anchor point. -- function MenuClass:SetAnchor(anchor) if anchor ~= 'cursor' then self.x = 0 self.y = 0 end self.anchor = anchor end -- ; displayMode : "MENU" -- function MenuClass:SetDisplayMode(displayMode) self.displayMode = displayMode end -- ; autoHideDelay : How long, without a click, before the menu goes away. -- function MenuClass:SetAutoHideDelay(autoHideDelay) self.autoHideDelay = tonumber(autoHideDelay) end -- ; menuFrame : Should inherit a Drop Down Menu template. -- function MenuClass:SetMenuFrame(menuFrame) self.menuFrame = menuFrame end function MenuClass:GetMenuList() return self.menuList end -- ; x : X position ; save : When not nil, will add to the current value rather than replace it -- function MenuClass:SetX(x, save) if save then self.x = self.x + x else self.x = x end end -- ; y : Y position ; save : When not nil, will add to the current value rather than replace it -- function MenuClass:SetY(y, save) if save then self.y = self.y + y else self.y = y end end function MenuClass:Activate() if not self.menuFrame then while _G'GenericMenuClassFrame'..self.uniqueID do -- ensure that there's no namespace collisions self.uniqueID = self.uniqueID + 1 end -- the frame must be named for some reason self.menuFrame = CreateFrame('Frame', 'GenericMenuClassFrame'..self.uniqueID, UIParent, "UIDropDownMenuTemplate") end self.menuFrame.menuList = self.menuList end -- Show the menu. -- function MenuClass:Show() self:Activate() EasyMenu(self.menuList, self.menuFrame, self.anchor, self.x, self.y, self.displayMode, self.autoHideDelay) end -- If you're not using the addon-scoped variables, you must have a global variable in order to use this menu. if not useAddonScope then _GaddonName.."Menu" = MenuClass end